跳到主要内容

开机自启动怎么实现?三个平台分别怎么处理?

考察点​

  • setLoginItemSettings 的跨平台行为
  • 静默启动、参数透传、各平台底层机制

参考答案​

1. 统一入口:app.setLoginItemSettings​

const { app } = require('electron');

// 开启开机自启
app.setLoginItemSettings({
openAtLogin: true,
openAsHidden: false, // macOS:是否以隐藏状态启动
args: ['--autostart'], // 启动参数,Windows 有效
});

// 查询当前状态
const { openAtLogin } = app.getLoginItemSettings();

2. 各平台底层机制​

Windows

  • 写入注册表 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run,键值为应用 exe 路径 + args
  • 只影响当前用户;要全用户需写 HKEY_LOCAL_MACHINE(需要管理员权限,一般不做)
  • Squirrel 时代的坑:快捷方式指向 Update.exe,自启路径要处理好版本目录变化;nsis 包则直接指向安装目录的 exe,相对稳定
  • 更可靠的做法:安装时由 nsis 脚本写注册表(卸载时同步清理)

macOS

  • 早期用 LSSharedFileList(Login Items),macOS 13+ 底层迁移到 SMAppService
  • openAsHidden: true 表示登录后以隐藏方式启动(agent 常用)
  • macOS 13+ 用户可在"系统设置 → 登录项"中看到并管理,应用名/图标展示要正常
  • 沙盒(MAS 上架)应用必须用 SMAppService + helper 的正规姿势

Linux

  • 没有统一 API,Electron 不支持,需自己写 .desktop 文件到 ~/.config/autostart/:
[Desktop Entry]
Type=Application
Name=MyAgent
Exec=/opt/myagent/myagent --autostart
X-GNOME-Autostart-enabled=true

3. Agent 静默启动模式​

开机自启时不应该弹窗打扰用户,通过 args 区分启动来源:

// main.js
const isAutostart = process.argv.includes('--autostart');

app.whenReady().then(() => {
createTray();
if (!isAutostart) {
createWindow(); // 手动启动才开窗,自启只驻留托盘
}
});

4. 常见坑​

  1. 开发环境测试:setLoginItemSettings 在开发模式指向的是 electron 可执行文件,测不出真实效果,必须打包后验证
  2. 应用更新后自启失效:安装路径变化(尤其 Squirrel 的 app-x.y.z 目录)导致注册表路径过期,更新后要重写一次
  3. macOS 签名变化:重新签名/公证后 Login Item 状态可能被重置,升级版本后要重新设置
  4. 企业管控环境:组策略可能禁用 Run 键自启,agent 需要备选方案(计划任务 / 服务)

面试话术​

跨平台用 setLoginItemSettings 统一处理,Windows 走注册表 Run 键、macOS 走 Login Items(13+ 是 SMAppService)、Linux 手写 autostart desktop 文件。工程上的重点是:args 传标记区分自启与手动启动实现静默驻留,以及版本更新后重新校正自启路径。

常见追问​

  • 用户禁止自启如何感知? getLoginItemSettings() 查询,设置页同步展示。
  • macOS 上怎么做到"登录时启动且 Dock 不显示"? LSUIElement(Info.plist)设为 true 让应用默认无 Dock 图标,或运行时 app.dock.hide()。